#define LOCAL_REGISTER		1
#define GLOBAL_REGISTER		2



typedef struct {
unsigned int src1, src2, dst;
bool src1Valid, src2Valid, dstValid;
bool integerRegisters;
} instructionsType;

typedef struct{
unsigned int src1, src2, dst;
unsigned int localSrc1, localSrc2, localDst;
unsigned char src1Status, src2Status, dstStatus;
bool src1Valid, src2Valid, dstValid;
bool integerRegisters;
} preRenamesInstructionType;

typedef struct{
unsigned int logicalRegister;
unsigned int localRegister;
unsigned char status;
}localRMTType;

int preRenamer(instructionsType *trace, unsigned int currentTraceWidth, preRenamesInstructionType *renamedTrace)
{
	
	localRMTType *localRMT;
	
	localRMT = new localRMTType[currentTraceWidth];
	int numLocalRMTEntries = 0;
	
	// First look at destination registers and see if they are local or global or both
	for ( int i = 0; i < currentTraceWidth; i++)
	{
		if (trace[i].dstValid)
		{ // See if the future intructions have the same destination register. If yes, someone is killing it => Not Golbal
			for (int j = i+1; j < currentTraceWidth; j++)
				{
					if (trace[j].dstValid && trace[i].dst == trace[j].dst)
					{
						renamedTrace[i].dstStatus &= ~GLOBAL_REGISTER;
						j = currentTraceWidth;
					}

					else //Global
						renamedTrace[i].dstStatus |= GLOBAL_REGISTER;

				}


		// Now, to avoid allocating local registers to the Global live-outs only
			int k;
			for (k = i+1; k < currentTraceWidth; k++)
			{
				if ( (trace[k].src1Valid && (trace[i].dst == trace[k].src1)) || (trace[k].src2Valid && (trace[i].dst == trace[k].src2)))
				{
					renamedTrace[i].dstStatus |= LOCAL_REGISTER;
					k = currentTraceWidth;
				}

			else
				renamedTrace[i].dstStatus &= ~LOCAL_REGISTER;
			}

		} //End dst valid
	}//End for loop



	for ( int i = 0; i < currentTraceWidth; i++)
	{

		//Rename the sources first. Assume source is a Global Live in
		renamedTrace[i].src1Status = GLOBAL_REGISTER;
		renamedTrace[i].src2Status = GLOBAL_REGISTER;

		//Maintain a local RMT and search through it for each source
		int j = numLocalRMTEntries -1;
		bool src1Done = false, src2Done = false;

		//Local RMT contains all the mappings that are renamed to locals. One entry per one local register
		for (; j>=0 && (!src1Done || !src2Done) ; j--)
			{
				if (trace[i].src1Valid)
					{
						if(!src1Done && localRMT[j].logicalRegister == trace[i].src1)
						{
							renamedTrace[i].localSrc1 = localRMT[j].localRegister;
							renamedTrace[i].src1Status = LOCAL_REGISTER | ~GLOBAL_REGISTER;
							src1Done = true;
						}
					}


				if (trace[i].src2Valid)
				{
					if(!src2Done && localRMT[j].logicalRegister == trace[i].src2)
					{
						renamedTrace[i].localSrc2 = localRMT[j].localRegister;
						renamedTrace[i].src2Status = LOCAL_REGISTER | ~GLOBAL_REGISTER;
						src2Done = true;
					}
				}
			}


		//Destination now:
		//Look at each destinations status register and decide

		if (trace[i].dstValid)
		{
			if (renamedTrace[i].dstStatus & LOCAL_REGISTER)
			{
				renamedTrace[i].localDst = numLocalRMTEntries;
				localRMT[numLocalRMTEntries].localRegister = numLocalRMTEntries;
				localRMT[numLocalRMTEntries].logicalRegister = trace[i].dst;
				numLocalRMTEntries ++;
			}
		}


	}
	


	return numLocalRMTEntries;
}

